package com.chii.gateway.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.chii.gateway.admin.client.GatewayClient;
import com.chii.gateway.admin.mapper.GatewayRouteMapper;
import com.chii.gateway.admin.po.FilterDefinition;
import com.chii.gateway.admin.po.GatewayRoute;
import com.chii.gateway.admin.po.PredicateDefinition;
import com.chii.gateway.admin.po.RouteDefinition;
import com.chii.gateway.admin.service.IGatewayRouteService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

@Service
public class GatewayRouteService implements IGatewayRouteService {
    private Logger logger = LogManager.getLogger(GatewayRouteService.class);
    private static final String GATEWAY_ROUTES = "gateway:routes";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private GatewayRouteMapper gatewayRouteMapper;
    @Autowired
    private GatewayClient gatewayClient;

    @Override
    public boolean add(GatewayRoute gatewayRoute) {
        int isSuccess = gatewayRouteMapper.insertSelective(gatewayRoute);
        // 转化为gateway需要的类型，缓存到redis, 并事件通知各网关应用
        RouteDefinition routeDefinition = gatewayRouteToRouteDefinition(gatewayRoute);

        stringRedisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),
                JSON.toJSONString(routeDefinition));

        gatewayClient.add(routeDefinition.getId(),JSON.toJSONString(routeDefinition));
        gatewayClient.refresh();
        return isSuccess == 1;
    }

    @Override
    public boolean delete(String id) {
        int isSuccess = gatewayRouteMapper.deleteByPrimaryKey(id);
        // 删除redis缓存, 并事件通知各网关应用
        stringRedisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);
        gatewayClient.del(id);
        gatewayClient.refresh();
        return isSuccess==1;
    }

    @Override
    public boolean update(GatewayRoute gatewayRoute) {
        int isSuccess = gatewayRouteMapper.updateByPrimaryKeySelective(gatewayRoute);

        // 转化为gateway需要的类型，缓存到redis, 并事件通知各网关应用
        RouteDefinition routeDefinition = gatewayRouteToRouteDefinition(gatewayRoute);
        stringRedisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),
                JSON.toJSONString(routeDefinition));

        gatewayClient.add(routeDefinition.getId(),JSON.toJSONString(routeDefinition));
        gatewayClient.refresh();

        return isSuccess==1;
    }

    /**
     * 将数据库中json对象转换为网关需要的RouteDefinition对象
     *
     * @param gatewayRoute
     * @return RouteDefinition
     */
    private RouteDefinition gatewayRouteToRouteDefinition(GatewayRoute gatewayRoute) {
        RouteDefinition routeDefinition = new RouteDefinition();
        routeDefinition.setId(gatewayRoute.getRouteId());
        routeDefinition.setOrder(gatewayRoute.getOrders());
        routeDefinition.setUri(URI.create(gatewayRoute.getUri()));
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            routeDefinition.setFilters(objectMapper.readValue(gatewayRoute.getFilters(), new TypeReference<>() {
            }));
            routeDefinition.setPredicates(objectMapper.readValue(gatewayRoute.getPredicates(), new TypeReference<>() {
            }));
        } catch (IOException e) {
            logger.error("网关路由对象转换失败", e);
        }
        return routeDefinition;
    }

    @Override
    public GatewayRoute get(String id) {
        return gatewayRouteMapper.selectByPrimaryKey(id);
    }

//    @Override
//    public List<GatewayRouteVo> query(GatewayRouteQueryParam gatewayRouteQueryParam) {
//        QueryWrapper<GatewayRoute> queryWrapper = gatewayRouteQueryParam.build();
//        queryWrapper.eq(StringUtils.isNotBlank(gatewayRouteQueryParam.getUri()), "uri", gatewayRouteQueryParam.getUri());
//        return this.list(queryWrapper).stream().map(GatewayRouteVo::new).collect(Collectors.toList());
//    }

    @Override
    @PostConstruct
    public boolean overload() {
        List<GatewayRoute> gatewayRoutes = gatewayRouteMapper.selectAll();
        gatewayRoutes.forEach(gatewayRoute ->
                stringRedisTemplate.opsForHash().put(GATEWAY_ROUTES, gatewayRoute.getRouteId(),
                        JSON.toJSONString(gatewayRouteToRouteDefinition(gatewayRoute)))
        );
        logger.info("全局初使化网关路由成功!");
        return true;
    }
}
